package com.insight.config.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.IRedisManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisClusterManager;
import org.crazycake.shiro.RedisManager;
import com.insight.common.constant.CommonConstant;
import com.insight.common.util.oConvertUtils;
import com.insight.config.shiro.filters.JwtFilter;
import com.insight.config.shiro.filters.OAuth2Filter;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.util.StringUtils;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.*;

/**
 * @author: Scott
 * @date: 2018/2/7
 * @description: shiro 配置类
 */

@Slf4j
@Component
@ConditionalOnProperty(name = "jeecg.shiro.excludeUrls")
public final  class ShiroConfig {

    @Value("${jeecg.shiro.excludeUrls}")
    private String excludeUrls;
    @Resource
    LettuceConnectionFactory lettuceConnectionFactory;
    @Autowired
    private Environment env;
    @Value("${jeecg.shiro.realm}")
    private String realm;

    /**
     * Filter Chain定义说明
     * <p>
     * 1、一个URL可以配置多个Filter，使用逗号分隔
     * 2、当设置多个过滤器时，全部验证通过，才视为通过
     * 3、部分过滤器可指定参数，如perms，roles
     */
    @Bean("shiroFilter")
    protected ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 拦截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        if (oConvertUtils.isNotEmpty(excludeUrls)) {
            String[] permissionUrl = excludeUrls.split(",");
            for (String url : permissionUrl) {
                filterChainDefinitionMap.put(url, "anon");
            }
        }
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/data/reportAndConverge/fullReport", "anon"); //qyb

        filterChainDefinitionMap.put("/data/reportAndConverge/dataHandle", "anon"); //数据汇聚上报接收接口
        filterChainDefinitionMap.put("/abutment/task/testAbutmentPull", "anon"); //（监控对接拉模式测试用）数据拉取接口
        filterChainDefinitionMap.put("/abutment/system/pieCount", "anon"); //监控对接推模式饼图
        filterChainDefinitionMap.put("/abutment/system/trendCount", "anon"); //监控对接推模式折线图

        filterChainDefinitionMap.put("/drive/driveInfo/download/**", "anon"); //驱动下载（计数接口）
        filterChainDefinitionMap.put("/software/softwareRepository/download/**", "anon"); //软件仓库下载（计数接口）
        filterChainDefinitionMap.put("/terminal/terminalDevice/terminalNational", "anon"); //终端根据区县统计国产化率-手动
        filterChainDefinitionMap.put("/sys/duplicate/check", "anon"); //指定表名、字段重复性校验
        filterChainDefinitionMap.put("/sys/user/addByTerminal", "anon"); //运维助手注册用户
        filterChainDefinitionMap.put("/sys/terminalLogin", "anon"); //运维助手用户登录
        filterChainDefinitionMap.put("/sys/terminalAutoLogin", "anon"); //运维助手自动登录
        filterChainDefinitionMap.put("/alarm/alarmLevel/getLevelList", "anon"); //获取告警级别
        filterChainDefinitionMap.put("/sys/user/receive", "anon"); //用户同步
        filterChainDefinitionMap.put("/sys/LoginRandom", "anon"); //ukeyh获取随机数
        filterChainDefinitionMap.put("/sys/UkeyLogin", "anon"); //ukey登录
        filterChainDefinitionMap.put("/sys/XJBTLogin", "anon");
        filterChainDefinitionMap.put("/sys/SZUKeyLogin", "anon");
        filterChainDefinitionMap.put("/sys/zyLogin", "anon");
        filterChainDefinitionMap.put("/terminal/terminalDevices/*", "anon"); // 测试ipmi
        //filterChainDefinitionMap.put("/device/statis/*","anon"); //部分接口需要用到用户信息，不能全部开放。如果需要单独开启接口过滤@wxp
        filterChainDefinitionMap.put("/device/statis/saveDeptAndStatis", "anon");
        filterChainDefinitionMap.put("/umpPwdManage/umpPwdManage/list", "anon"); // 启动修改密码获取规则，无需token
        filterChainDefinitionMap.put("/sys/common/upload", "anon");
        filterChainDefinitionMap.put("/sys/log/exportXls", "anon");
        filterChainDefinitionMap.put("/devopsipmanage/devopsIpManage/downloadTemplate", "anon");//下载模板不需要tonken
        filterChainDefinitionMap.put("/sys/message/sysMessageTemplate/downloadTemplate", "anon");//下载模板不需要tonken
        filterChainDefinitionMap.put("/sys/dict/downloadTemplate", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/queryAllDepts", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/queryAllTree", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/queryById", "anon");
        filterChainDefinitionMap.put("/license/importLicense", "anon");
        filterChainDefinitionMap.put("/license/installLicense", "anon");
        filterChainDefinitionMap.put("/license/getDetails", "anon");
        filterChainDefinitionMap.put("/license/licenseTest", "anon");
        filterChainDefinitionMap.put("/license/getServerInfo", "anon");
        filterChainDefinitionMap.put("/license/alarm/list", "anon");
        filterChainDefinitionMap.put("/open/ops/application/data", "anon");
        filterChainDefinitionMap.put("/category/cmdbAssetsCategory1/exportXls", "anon");
        filterChainDefinitionMap.put("/category/cmdbAssetsCategory1/downloadTemplate", "anon");
        filterChainDefinitionMap.put("/assets/assets/downloadTemplate", "anon");
        filterChainDefinitionMap.put("/*", "anon");
        filterChainDefinitionMap.put("/console/influxdb/*", "anon");
        filterChainDefinitionMap.put("/itilStockInfo/itilStockInfo/*", "anon");
        filterChainDefinitionMap.put("/relation/cmdbRelation/downloadTemplate", "anon");
        filterChainDefinitionMap.put("/wx/REDIRECT_URI", "anon");
        filterChainDefinitionMap.put("/wx/getWx", "anon");
        filterChainDefinitionMap.put("/wx/test", "anon");
        filterChainDefinitionMap.put("/wx/testSend", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/count/date", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/overview", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/realtime", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/history", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/device/days", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/alarmLevelTrend", "anon");
        filterChainDefinitionMap.put("/status/cmdbStatus/*", "anon");
        filterChainDefinitionMap.put("/extendForm/extendForm/*", "anon");
        //  filterChainDefinitionMap.put("/approve/momgTerminalApprove/*","anon");  //部分接口需要用到用户信息，不能全部开放。如果需要单独开启接口过滤@wxp
        // filterChainDefinitionMap.put("/terminal/terminalDevice/*","anon");
//        filterChainDefinitionMap.put("/terminal/terminalDevice/updateStatus", "anon");
//        filterChainDefinitionMap.put("/terminal/terminalDevice/exportXls","anon");
        filterChainDefinitionMap.put("/terminal/terminalDevice/downloadTemplate", "anon");
        filterChainDefinitionMap.put("/terminal/terminalDevice/getTerminalInfoByMac", "anon");
        filterChainDefinitionMap.put("/temp/*", "anon");

        filterChainDefinitionMap.put("/user/*", "anon");


        filterChainDefinitionMap.put("/software/*", "anon");
        //filterChainDefinitionMap.put("/data-analysis/terminal/**", "anon");
        //filterChainDefinitionMap.put("/data-analysis/topo/*", "anon");
        //filterChainDefinitionMap.put("/data-analysis/*", "anon");
        //filterChainDefinitionMap.put("/data-analysis/alarm/*", "anon");
        //filterChainDefinitionMap.put("/data-analysis/device/*", "anon");
        //filterChainDefinitionMap.put("/data-analysis/order/*", "anon");
        filterChainDefinitionMap.put("/sys/notice/template/*", "anon");
        filterChainDefinitionMap.put("/sys/notice/config/*", "anon");
        //filterChainDefinitionMap.put("/product/deviceConnectTemplateInfo/*","anon");
        filterChainDefinitionMap.put("/gateway/deviceInfo/*", "anon");
        filterChainDefinitionMap.put("/patch/software/*", "anon"); //软件分发接口, 给进程守护使用, 无需权限
//        filterChainDefinitionMap.put("/assets/assets/*","anon");
//        filterChainDefinitionMap.put("/supplier/cmdbSupplier/*","anon");
        filterChainDefinitionMap.put("/supplier/cmdbSupplier/downloadTemplate", "anon");// 开放供应商管理中Excel导入权限
        filterChainDefinitionMap.put("/sys/dict/getAreaTree", "anon");
        filterChainDefinitionMap.put("/sys/dict/getDictItem/*", "anon");
        filterChainDefinitionMap.put("/topoCabinet2device/topoCabinet2device/*", "anon");
        filterChainDefinitionMap.put("/topo/cabinet/*", "anon");
        filterChainDefinitionMap.put("/topo/room/*", "anon");
        filterChainDefinitionMap.put("/topo/topoInfo/*", "anon");

        //字典项获取排除，运维助手注册时使用
        filterChainDefinitionMap.put("/sys/dict/getDictItems/*", "anon");

        filterChainDefinitionMap.put("/sys/dict/getDictCodeChild", "anon");
        filterChainDefinitionMap.put("/device/deviceCategory/*", "anon");
        filterChainDefinitionMap.put("/topo/device/*", "anon");
        filterChainDefinitionMap.put("/topo/device/icon/add", "anon");
        // filterChainDefinitionMap.put("/device/deviceInfo/topo/deviceInfo","anon");
        // filterChainDefinitionMap.put("/device/deviceInfo/topo/deviceTree","anon");
        filterChainDefinitionMap.put("/devopsipmanagereal/devopsIpManageReal/*", "anon");
        filterChainDefinitionMap.put("/assetscategory/assetsCategory/*", "anon");//资产类型
        //filterChainDefinitionMap.put("/product/proertyMetadata/*","anon");
        filterChainDefinitionMap.put("/alarm/alarmTemplate/*", "anon");//模板告警

        filterChainDefinitionMap.put("/reportassess/itilReportAssessInfo/getList", "anon");//测试

        filterChainDefinitionMap.put("/test1", "anon");//测试BEAN
        filterChainDefinitionMap.put("/device/deviceProduct/*", "anon");
        filterChainDefinitionMap.put("/ssh/getPath", "anon");

        filterChainDefinitionMap.put("/sys/user/updatePassword", "anon");
        filterChainDefinitionMap.put("/sys/user/addBatch", "anon");
        filterChainDefinitionMap.put("/sys/user/getPwd", "anon");

        filterChainDefinitionMap.put("/sys/sysDepart/outDepList", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/outListPage", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/outAdd", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/outAdit", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/outAddList", "anon");
        filterChainDefinitionMap.put("/sys/sysDepart/testMove", "anon"); // 数据迁移接口，请勿删除

        filterChainDefinitionMap.put("/wx/sendMessage", "anon"); //消息发送接口
        //filterChainDefinitionMap.put("/product/product/*", "anon"); //cas验证登录
        //filterChainDefinitionMap.put("/device/deviceInfo/*", "anon"); //cas验证登录
        filterChainDefinitionMap.put("/monitoring/*", "anon"); //cas验证登录
        filterChainDefinitionMap.put("/accountbook/*", "anon"); //cas验证登录
        filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
        filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
        filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
        filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
        filterChainDefinitionMap.put("/sys/hkLogin", "anon"); //登录接口排除
        filterChainDefinitionMap.put("/sys/autoLogin", "anon"); //登录接口排除
        filterChainDefinitionMap.put("/sys/getToken", "anon"); //登录接口排除
        filterChainDefinitionMap.put("/sys/mpLogin", "anon"); //登录接口排除
        filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
        filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
        filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
        filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
        filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
        filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
        filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
        filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
        filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息
        filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
        filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
        filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
        filterChainDefinitionMap.put("/sys/common/*", "anon");//图片预览 &下载文件不限制token
        filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
        filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
        filterChainDefinitionMap.put("/sys/common/view/**", "anon");//图片预览不限制token
        filterChainDefinitionMap.put("/sys/common/download/**", "anon");//文件下载不限制token /sys/common/download
        filterChainDefinitionMap.put("/sys/common/downloadFile/**", "anon");//文件下载不限制token /sys/common/download
        filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/doc.html", "anon");
        filterChainDefinitionMap.put("/**/*.js", "anon");
        filterChainDefinitionMap.put("/**/*.css", "anon");
        filterChainDefinitionMap.put("/**/*.html", "anon");
        filterChainDefinitionMap.put("/**/*.svg", "anon");
        filterChainDefinitionMap.put("/**/*.pdf", "anon");
        filterChainDefinitionMap.put("/**/*.glb", "anon");
        filterChainDefinitionMap.put("/**/*.jpg", "anon");
        filterChainDefinitionMap.put("/**/*.png", "anon");
        filterChainDefinitionMap.put("/**/*.ico", "anon");
        filterChainDefinitionMap.put("/sys/dict/getSysAreaList", "anon");
        //activiti
        filterChainDefinitionMap.put("/activiti/**", "anon");
        filterChainDefinitionMap.put("/diagram-viewer/**", "anon");
        filterChainDefinitionMap.put("/editor-app/**", "anon");
        filterChainDefinitionMap.put("/sys/user/userList", "anon");
        filterChainDefinitionMap.put("/sys/role/roleList", "anon");
        // update-begin--Author:sunjianlei Date:20190813 for：排除字体格式的后缀
        filterChainDefinitionMap.put("/**/*.ttf", "anon");
        filterChainDefinitionMap.put("/**/*.woff", "anon");
        filterChainDefinitionMap.put("/**/*.woff2", "anon");
        // update-begin--Author:sunjianlei Date:20190813 for：排除字体格式的后缀

        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger**/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");

        //积木报表排除
        filterChainDefinitionMap.put("/jmreport/**", "anon");
        filterChainDefinitionMap.put("/**/*.js.map", "anon");
        filterChainDefinitionMap.put("/**/*.css.map", "anon");

        //测试示例
        filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
        filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子
        //filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
        //filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试

        //websocket排除
        filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
        filterChainDefinitionMap.put("/ipmanagerreal/**", "anon");//系统通知和公告
        filterChainDefinitionMap.put("/webssh/**", "anon");//
        filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
        //TODO:: 测试模板的通知发送
        filterChainDefinitionMap.put("/test/sendMessage", "anon");//JVxeTable无痕刷新示例

        //性能监控  TODO 存在安全漏洞
        //filterChainDefinitionMap.put("/actuator/**", "anon");

        //模板下载
        filterChainDefinitionMap.put("/ledger/**/downloadTemplate", "anon");
        //todo:如恒解决前端404问题
        filterChainDefinitionMap.put("/gateway/*", "anon");
        filterChainDefinitionMap.put("/bigscreen/*", "anon");
        filterChainDefinitionMap.put("/bigscreen/*/*", "anon");
        filterChainDefinitionMap.put("/dist/*", "anon");
        filterChainDefinitionMap.put("/dist/*/*", "anon");
        filterChainDefinitionMap.put("/dist/*/*/*", "anon");

        filterChainDefinitionMap.put("/oneClickHelp/*", "anon");
        filterChainDefinitionMap.put("/zfnw/*", "anon");
        filterChainDefinitionMap.put("/kbase/knowledges/share/check/*", "anon");
        filterChainDefinitionMap.put("/kbase/knowledges/share/avatar", "anon");
        filterChainDefinitionMap.put("/kbase/knowledges/searchKnowledge", "anon");
        filterChainDefinitionMap.put("/kbase/knowledges/getHotSearch", "anon");
        //开放api
        filterChainDefinitionMap.put("/openAPI/*", "anon");
        //soap
        filterChainDefinitionMap.put("/service/*", "anon");
        filterChainDefinitionMap.put("/drive/driveInfo/list", "anon");
        filterChainDefinitionMap.put("/drive/driveInfo/getCpuOsType", "anon");

        filterChainDefinitionMap.put("/alarm/alarmLevel/list","anon");
        filterChainDefinitionMap.put("/topo/autoTopo/*","anon");

        filterChainDefinitionMap.put("/topo/autoTopo/*","anon");
        filterChainDefinitionMap.put("/software/upgradePackageManage/download/**", "anon");

        //深圳大屏排除
        filterChainDefinitionMap.put("/data-analysis/topo/room/tree2", "anon");
        filterChainDefinitionMap.put("/topo/topoInfo/list", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/realtime", "anon");
        filterChainDefinitionMap.put("/data-analysis/alarm/alarmLevelTrend", "anon");
        filterChainDefinitionMap.put("/data-analysis/order/countByType", "anon");
        filterChainDefinitionMap.put("/duty/shift/queryUsersByWeek", "anon");
        filterChainDefinitionMap.put("/data-analysis/order/trendStatistics", "anon");
        filterChainDefinitionMap.put("/topo/device/tree", "anon");
        filterChainDefinitionMap.put("/topo/room/info", "anon");
        filterChainDefinitionMap.put("/topo/topoInfo/queryById", "anon");
        filterChainDefinitionMap.put("/topo/room/includeDevices", "anon");

        //实验室预约大屏
        filterChainDefinitionMap.put("/reservations/getTodayReservations", "anon");
        filterChainDefinitionMap.put("/reservations/getCurrentReservation", "anon");

        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
        //如果cloudServer为空 则说明是单体 需要加载跨域配置
        Object cloudServer = env.getProperty(CommonConstant.CLOUD_SERVER_KEY);
        filterMap.put("jwt", new JwtFilter(cloudServer == null));
        filterMap.put("oauth2", new OAuth2Filter(cloudServer == null));
        shiroFilterFactoryBean.setFilters(filterMap);
        // <!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边
        filterChainDefinitionMap.put("/**", realm);

        // 未授权界面返回JSON
        shiroFilterFactoryBean.setUnauthorizedUrl("/sys/common/403");
        shiroFilterFactoryBean.setLoginUrl("/sys/common/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager(List<Realm> realmList) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealms(realmList);

        /*
         * 关闭shiro自带的session，详情见文档
         * http://shiro.apache.org/session-management.html#SessionManagement-
         * StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(true);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        //自定义缓存实现,使用redis
        securityManager.setCacheManager(redisCacheManager());
        return securityManager;
    }

    /**
     * 下面的代码是添加注解支持
     *
     * @return
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        /**
         * 解决重复代理问题 github#994
         * 添加前缀判断 不匹配 任何Advisor
         */
        defaultAdvisorAutoProxyCreator.setUsePrefix(true);
        defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }


    /**
     * cacheManager 缓存 redis实现
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisCacheManager redisCacheManager() {

        log.info("===============(1)创建缓存管理器RedisCacheManager");
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        //redis中针对不同用户缓存(此处的id需要对应user实体中的id字段,用于唯一标识)
        redisCacheManager.setPrincipalIdFieldName("id");
        //用户权限信息缓存时间

        redisCacheManager.setExpire(20000);
        return redisCacheManager;
    }

    /**
     * 配置shiro redisManager
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    @Bean
    public IRedisManager redisManager() {
        log.info("===============(2)创建RedisManager,连接Redis..");
        IRedisManager manager;
        // redis 单机支持，在集群为空，或者集群无机器时候使用 add by jzyadmin@163.com
        if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
            RedisManager redisManager = new RedisManager();
            redisManager.setHost(lettuceConnectionFactory.getHostName());
            redisManager.setPort(lettuceConnectionFactory.getPort());
            redisManager.setTimeout(0);
            if (!StringUtils.isEmpty(lettuceConnectionFactory.getPassword())) {
                redisManager.setPassword(lettuceConnectionFactory.getPassword());
            }
            manager = redisManager;
        } else {
            // redis 集群支持，优先使用集群配置	add by jzyadmin@163.com
            RedisClusterManager redisManager = new RedisClusterManager();
            Set<HostAndPort> portSet = new HashSet<>();
            lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost(), node.getPort())));
            JedisCluster jedisCluster = new JedisCluster(portSet);
            redisManager.setJedisCluster(jedisCluster);
            manager = redisManager;
        }
        return manager;
    }

}
